%% Recognize the technical patterns automatically
% Using close price in database to compute the Kernel regression esimator

% rslt = get_info_from_database('security', 'sec_id', 405, ...
%     'from', '01/01/2009', 'to', '31/12/2012');
% close_prc = rslt(1:end-2,6);

function [count_pattern window_opt] = patternRec3(close_prc)

% Change window to find out the highest number of patterns
% window = [38];
window = [34,36,38,40,42,61,63,65];
% Count the total patterns in all periods
total_pattern = zeros(length(window),10);
count = [];
for a = 1:length(window)  
    len = length(close_prc) - window(a) + 1;
    pattern_grid = zeros(len, 10);
    for i = 1:len
        HS = 0;%
        IHS = 0;
        BTOP = 0;
        BBOT = 0;
        TTOP = 0;
        TBOT = 0;
        RTOP = 0;
        RBOT = 0;
        DTOP = 0;
        DBOT = 0;
        
        ind_extrema_max = [];
        ind_extrema_min = [];
        
        y = close_prc(i:i+window(a)-1);
        x = 1:window(a);
        r = ksr(x,y,window(a));
        deri = r.f(2:end) - r.f(1:end-1);
        
        for j = 1: (length(deri)-1)
            if sign(deri(j+1)) < sign(deri(j))
                ind_extrema_max = horzcat(ind_extrema_max,j+1);
            elseif sign(deri(j+1)) > sign(deri(j))
                ind_extrema_min = horzcat(ind_extrema_min,j+1);
                %      all_extrema{i} = ind_extrema;
            end
        end
        
        extrema_max = r.f(ind_extrema_max);
        extrema_min = r.f(ind_extrema_min);
        idx_extrema = sort(horzcat(ind_extrema_max,ind_extrema_min));
        extrema = r.f(idx_extrema);
        
        % Detect 5 patterns:
        for k = 1: (length(extrema) - 5)
            pattern = extrema(k:k+4);
            ave13 = .5*(pattern(1)+ pattern(3));
            ave15 = .5*(pattern(1)+ pattern(5));
            ave24 = .5*(pattern(2)+ pattern(4));
            ave35 = .5*(pattern(3)+ pattern(5));
            
            % Head and Shoulders and Inverse H&S (1)
            
            if isempty(find(extrema_min == pattern(1), 1))...
                    && pattern(3) > pattern(1) && pattern(3) > pattern(5)...
                    && abs(pattern(1) - ave15)/ave15 <= 0.015 ...
                    && abs(pattern(5) - ave15)/ave15 <= 0.015 ...
                    && abs(pattern(2) - ave24)/ave24 <= 0.015 ...
                    && abs(pattern(4) - ave24)/ave24 <= 0.015
                HS = 1;
%                 kHS = k;
            elseif isempty(find(extrema_max == pattern(1), 1))...
                    && pattern(3) < pattern(1) && pattern(3) < pattern(5)...
                    && abs(pattern(1) - ave15)/ave15 <= 0.015 ...
                    && abs(pattern(5) - ave15)/ave15 <= 0.015 ...
                    && abs(pattern(2) - ave24)/ave24 <= 0.015 ...
                    && abs(pattern(4) - ave24)/ave24 <= 0.015
                IHS = 1;
%                 kIHS = k;
            end
            
            % Broadening tops and bottoms (2)
            
            if isempty(find(extrema_min == pattern(1), 1))...
                    && pattern(1) < pattern(3) < pattern(5)...
                    && pattern(2) > pattern(4)
                BTOP = 1;
%                 k_BTOP = k;
            elseif isempty(find(extrema_max == pattern(1), 1))...
                    && pattern(1) > pattern(3) > pattern(5)...
                    && pattern(2) < pattern(4)
                BBOT = 1;
%                 k_BBOT = k;
            end
            
            % Triangle tops and bottoms (3)
            
            if isempty(find(extrema_min == pattern(1), 1))...
                    && pattern(1) > pattern(3) > pattern(5)...
                    && pattern(2) < pattern(4)
                TTOP = 1;
%                 k_TTOP = k;
            elseif isempty(find(extrema_max == pattern(1), 1))...
                    && pattern(1) < pattern(3) < pattern(5)...
                    && pattern(2) > pattern(4)
                TBOT = 1;
%                 k_TBOT = k;
            end
            
            % Rectangle tops and bottoms (4)
            if isempty(find(extrema_min == pattern(1), 1))...
                    && abs(pattern(1) - ave13)/ave13 <= 0.0075...
                    && abs(pattern(1) - ave15)/ave15 <= 0.0075...
                    && abs(pattern(3) - ave13)/ave13 <= 0.0075...
                    && abs(pattern(3) - ave35)/ave35 <= 0.0075...
                    && abs(pattern(5) - ave15)/ave15 <= 0.0075...
                    && abs(pattern(5) - ave35)/ave35 <= 0.0075...
                    && abs(pattern(2) - ave24)/ave24 <= 0.0075...
                    && abs(pattern(4) - ave24)/ave24 <= 0.0075...
                    && min(pattern([1 3 5])) ...
                    > max(pattern(2),pattern(4))
                
                RTOP = 1;
%                 k_RTOP = k;
            elseif isempty(find(extrema_max == pattern(1), 1))...
                    && abs(pattern(1) - ave13)/ave13 <= 0.0075...
                    && abs(pattern(1) - ave15)/ave15 <= 0.0075...
                    && abs(pattern(3) - ave13)/ave13 <= 0.0075...
                    && abs(pattern(3) - ave35)/ave35 <= 0.0075...
                    && abs(pattern(5) - ave15)/ave15 <= 0.0075...
                    && abs(pattern(5) - ave35)/ave35 <= 0.0075...
                    && abs(pattern(2) - ave24)/ave24 <= 0.0075...
                    && abs(pattern(4) - ave24)/ave24 <= 0.0075...
                    && min(pattern(2),pattern(4)) ...
                    > max(pattern([1 3 5]))
                
                RBOT = 1;
%                 k_RBOT = k;
            end
        end
        
        % Double tops and bottoms (5)
        for m = 1: (length(extrema_max) - 1)
            [highest_max, idx_highest_max] = max(extrema_max(m+1:length(extrema_max)));
            % index for E_a
            idx_max_a = ind_extrema_max(m+idx_highest_max);
            % index for E_1
            idx_max_1 = ind_extrema_max(m);
            
            ave_max = .5*(extrema_max(m) + highest_max);
            if abs(extrema_max(m) - ave_max)/ave_max <= 0.015...
                    && abs(highest_max - ave_max)/ave_max <= 0.015...
                    && (idx_max_a - idx_max_1) > 22
                patRec.DTOP = 1;
%                 m_DTOP = m;
            end
        end
        
        for m = 1: (length(extrema_min) - 1)
            [lowest_min, idx_lowest_min] = min(extrema_min(m+1:length(extrema_min)));
            % index for E_b
            idx_min_b = ind_extrema_min(m+idx_lowest_min);
            % index for E_1
            idx_min_1 = ind_extrema_min(m);
            % index for E_1
            
            ave_min = .5* (extrema_min(m) + lowest_min);
            if abs(extrema_min(m) - ave_min)/ave_min <= 0.015...
                    && abs(lowest_min - ave_min)/ave_min <= 0.015...
                    && idx_min_b - idx_min_1  > 22
                
                patRec.DBOT = 1;
                
%                 m_DBOT = m;
            end
        end
        
        
        if any([HS, IHS, BTOP, BBOT, TTOP, TBOT, RTOP, RBOT, DTOP, DBOT])
            
            pattern_grid(i,1) = HS;
            pattern_grid(i,2) = IHS;
            pattern_grid(i,3) = BTOP ;
            pattern_grid(i,4) = BBOT ;
            pattern_grid(i,5) = TTOP ;
            pattern_grid(i,6) = TBOT ;
            pattern_grid(i,7) = RTOP ;
            pattern_grid(i,8) = RBOT ;
            pattern_grid(i,9) = DTOP ;
            pattern_grid(i,10)= DBOT ;
            
        end
     
    end
    
    % get the sum # of pattern find in period
    total_pattern(a,:) = sum(pattern_grid,1);
%     total_pattern_avg(a,:) = total_pattern(a,:)/len;    % divide to # windows
    count = [count;pattern_grid];
end

%sort to get the optimal value of window
[value idx] = sort(sum(total_pattern,2),'descend');
idx_adj = 0;
c = 0;

for b = 1:length(window)
    if b < idx(1,1)
        c =  length(close_prc) - window(b) + 1;
        idx_adj = idx_adj + c;
    end
end
    count_pattern = count(idx_adj+1:idx_adj+length(close_prc) - window(idx(1,1))+1,:);
    window_opt = window(idx(1,1));
end
